package prv.pursuivant.armory.impl;

import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;

import prv.pursuivant.core.Achievement;
import prv.pursuivant.core.Toon;
import prv.pursuivant.core.impl.AchievementImpl;
import prv.pursuivant.core.impl.ToonImpl;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * Factory class to instantiate XStream serializers
 * 
 * @author Kwinto
 */
public class XStreamCacheFactory {

	/**
	 * 
	 * @return
	 */

	public XStream createXStreamForToon(final Toon toon) {
		XStream xstream = new XStream(new DomDriver());
		xstream.useAttributeFor(String.class);
		xstream.useAttributeFor(Integer.class);
		xstream.useAttributeFor(Boolean.class);
		xstream.useAttributeFor(ToonImpl.class);
		xstream.useAttributeFor(Date.class);
		xstream.alias("achiev", AchievementImpl.class);
		xstream.registerConverter(new Converter() {

			final DateFormat dateFormat = DateFormat
					.getDateInstance(DateFormat.MEDIUM);

			@Override
			public void marshal(Object source, HierarchicalStreamWriter writer,
					MarshallingContext context) {
				if (source instanceof AchievementImpl) {
					Achievement achiev = (Achievement) source;
					writer.addAttribute("id", achiev.getId());
					writer.addAttribute("date", dateFormat.format(achiev
							.getDate()));
				}
			}

			@Override
			public Object unmarshal(HierarchicalStreamReader reader,
					UnmarshallingContext context) {
				String id = reader.getAttribute("id");
				String dateStr = reader.getAttribute("date");
				Date date;
				try {
					date = dateFormat.parse(dateStr);
				} catch (ParseException e) {
					date = null;
				}
				return new AchievementImpl(toon, date, id);
			}

			@SuppressWarnings("unchecked")
			@Override
			public boolean canConvert(Class type) {
				return type.equals(AchievementImpl.class);
			}
		});
		return xstream;
	}
}
